/*!
提供WEB模式下的gfs使用demo
 - 只提供基于当前服务器的基本的读写看能力。
 - 因为当前router把此服务器拓扑为一个完整gfs，所以不具备完整的gfs能力，尤其在扩展性，以及冗余备份和负载分担方面。
 - 总上，demo只做演示，不做生产。
 - 更好的应用展示，请参见:
    * [gfsc/demo](https://gitee.com/lenssh/rabbit/blob/master/gfsc/src/bin/demo.rs)
    * [gfsc/examples](https://gitee.com/lenssh/rabbit/tree/master/gfsc/examples)
 */

use axum::{   
    response::{Html,Response, IntoResponse},
    extract::{ State , Multipart}    
};
use axum::response::Result as AResult;
use crate::*;


pub async fn default_index(State(shared): State<SharedHandle>) -> impl IntoResponse {
    
    let router = GfsRouter::localhost_router(shared.port);
    let files = gfsc_get_files(&router, router.cur_dynasty, 0, 10).await;
    //} Html<&'static str> {
    let mut builder = String::new();
    builder.push_str(r#"<html><body><div align=center>"#);
    builder.push_str(r#"<h1>THIS IS A DEMO FOR gfs!</h1>"#);
    builder.push_str(r#"</div><BR><div align=center><a href='/admin/status/admin***?f=html'>gfs status</a></div>"#);    
    builder.push_str(r#"<div align=center><table>"#);    
    builder.push_str(r#"<tr><td><a href="/demo/form/file"> upload file </a></td></tr>"#);
    builder.push_str(r#"<tr><td>  ...  ...  </td></tr>"#);
    builder.push_str(r#"<tr><td><a href="/whereis/filename"> whereis filename </a></td></tr>"#);
    builder.push_str(r#"<tr><td><a href="/grep/file/pattern"> grep file name </a></td></tr>"#);
    builder.push_str(r#"<tr><td><a href="/search?q=hello"> search </a></td></tr>"#);
    builder.push_str(
        r#"<tr><td><BR><pre>
let router = <B>gfsc_new_router(conf)</B>?;        
router.check()?;
let files = <B>gfsc_get_files</B>(&router, dynasty, 0, 10)</pre><BR> </td></tr>"#,
    );
    builder.push_str(
        r#"<tr><td><pre>
let down_url = <b>router.get_download_url</b>(dynasty, idx, ihash, name.as_str())?;
let preview_url = <b>router.get_reader_url</b>(dynasty, idx, ihash, name.as_str())?; 
let image_url = <b>router.get_image_url</b>(dynasty, idx, ihash, name.as_str())?;   
</pre></td></tr>"#,
    );

    if let Ok(files) = files {
        for i in 0..files.len() {
            let ihash = hex::decode(files[i].fhash.as_str()).unwrap()[0] as i32;
            let down_url =router
                .get_download_url(
                    router.cur_dynasty,
                    files[i].id,
                    ihash,
                    files[i].name.as_str(),
                )
                .unwrap();

            builder.push_str(r#"<tr><td><BR><BR> download <a href=""#);
            builder.push_str(down_url.as_str());
            builder.push_str(r#""> "#);
            builder.push_str(files[i].name.as_str());
            builder.push_str(r#" </a></td></tr>"#);

            let ext: Vec<&str> = files[i].name.split(".").collect();
            if ext.len() > 0 {
                // let texts = vec!["txt", "docx", "pptx", "xlsx", "py", "rs", "go"];
                // let images = vec!["png", "jpg", "jpeg"];
                let ext = ext[ext.len() - 1];
                if is_preview_file(ext) {
                    let preview_url = router
                        .get_reader_url(
                            router.cur_dynasty,
                            files[i].id,
                            ihash,
                            files[i].name.as_str(),
                        )
                        .unwrap();
                    builder.push_str(r#"<tr><td> preview <a href=""#);
                    builder.push_str(preview_url.as_str());
                    builder.push_str(r#"">"#);
                    builder.push_str(files[i].name.as_str());
                    builder.push_str(r#" </a></td></tr>"#);
                }
                if is_image_file(ext){
                    let image_url = router
                        .get_image_url(
                            router.cur_dynasty,
                            files[i].id,
                            ihash,
                            files[i].name.as_str(),
                        )
                        .unwrap();
                    builder.push_str(r#"<tr><td> image online view <a href=""#);
                    builder.push_str(image_url.as_str());
                    builder.push_str(r#"">"#);
                    builder.push_str(files[i].name.as_str());
                    builder.push_str(r#" </a> </td></tr>"#);
                }
            }
            if i >= 3 {
                break;
            }
        }
        builder.push_str(
            r#"<tr><td><BR><BR><pre>
let files = <B>gfsc_get_dir</B>(&router, dynasty, ihash, idx, limit).await;        
if let Ok(files) = files{
    ...
}
</pre></td></tr>"#,
        );

        if files.len() > 0 {
            builder.push_str(r#"<tr><td>dir Demo : "#);
            let ihash = hex::decode(files[0].fhash.as_str()).unwrap()[0] as u32;
            let token = new_token();
            builder.push_str(
                format!(
                    "<a href='/dir?token={}&ihash={}&idx=0&limit=32'>{}</a> ",
                    token, ihash, files[0].fhash
                )
                .as_str(),
            );
            builder.push_str(r#"</td></tr>"#);
        }
    }

    builder.push_str(r#"</table></div></body></html>"#);
    Html(builder)
}

/// Handler that accepts a multipart form upload and streams each field to a file.
pub async fn demo_form_file(
    State(shared): State<SharedHandle>,
    mut multipart: Multipart,
) -> AResult<Response, MyError> {    
    let mut rets: Vec<GfsResponse> = Vec::new();
    // 实际应用中，router应该放入SharedHandle，而不是每次都去载入解析。
    let router = GfsRouter::localhost_router(shared.port);    
    while let Some(field) = multipart.next_field().await.unwrap() {
        let file_name = if let Some(file_name) = field.file_name() {
            file_name.to_owned()
        } else {
            continue;
        };
        
        if let Ok(ret) = gfsc_stream_to_gfs(&router, &file_name, field).await {
            rets.push(ret);
        }        
    }
    
    let mut html = String::new();
    html.push_str("<html><body><div align=center><h1>gfs应用demo </h1><BR> <span>返回数据，文件在gfs的定位信息, 应用方应该保存！！ </span><BR><BR>");
    if rets.len() == 0 {
        html.push_str("Sorry, No result!");
    }
    html.push_str("<table><tr><td width=600></td></tr>");
    for s in rets {
        html.push_str( format!("<tr><td>dynasty={}, idx={}, name = {}</td></tr>",router.cur_dynasty, s.idx, s.name.as_str() ).as_str());
        let dlink = router.get_download_url(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?;
        html.push_str( format!("<tr><td><a href='{}'>download it </a></td></tr>", dlink ).as_str());
        let plink = router.get_reader_url(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?; 
        html.push_str( format!("<tr><td> <a href='{}'>preview it </a>(文本文件)</td></tr>", plink ).as_str());
        let ilink = router.get_image_url(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?;
        html.push_str( format!("<tr><td> <a href='{}'>image link</a>(图片文件)</td></tr>", ilink ).as_str());
    }
    html.push_str("</table><BR><BR>");
    html.push_str(r#"<table><tr><td><pre align=left>
    let cur_dynasty = 0
    for s in rets {
        html.push_str( format!("dynasty={}, idx={}, name = {}", cur_dynasty, s.idx, s.name.as_str() ).as_str());
        let dlink = <b>router.get_download_url</b>(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?;
        html.push_str( format!("a href=", dlink ).as_str());
        let plink = <b>router.get_reader_url</b>(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?; 
        html.push_str( format!("a href='{}'", plink ).as_str());
        let ilink = <b>router.get_image_url</b>(router.cur_dynasty, s.idx, s.ihash, s.name.as_str())?;
        html.push_str( format!("a href='{}'", ilink ).as_str());
    }
    </pre></td></tr></table>
    "#);
    html.push_str("</div>");
    // reader, image, download    
    html.push_str("</body></html>");
    AResult::Ok( Html(html).into_response())
}

/// Handler that returns HTML for a multipart form.
pub async fn demo_file_form() -> Html<&'static str> {
    Html(
        r#"
        <!doctype html>
        <html>
            <head>
                <title>Upload something!</title>
            </head>
            <body>
            <div><h1 align=center>gfs实用案例</h1></div><BR>
            <div align=center>        
            <span> 应用场景中接到post的file后，调用 <b>stream_to_gfs()</b>，直接把收到的数据写入gfs系统，保存gfs返回的存储信息：dynasty_id, filename, idx。</span><BR>
            <span><pre align=left>
            let mut rets: Vec<GfsResponse> = Vec::new();
            // 实际应用中，router应该放入State ，而不是每次都去载入解析。
            let router = shared.gfs.root.join("router.json");
            let router = GfsRouter::new(router.display().to_string().as_str());
            
            while let Some(field) = multipart.next_field().await.unwrap() {
                let file_name = if let Some(file_name) = field.file_name() {
                    file_name.to_owned()
                } else {
                    continue;
                };
                
                if let Ok(ret) = <b>stream_to_gfs(&router, &file_name, field).await</b> {
                    rets.push(ret);
                }        
            }
            </pre>
            </span>            
                <table><tr><td width=600>
                <form action="/demo/form/file" method="post" enctype="multipart/form-data">
                    <div>
                        <label>
                            Upload file:
                            <input type="file" name="file" multiple>
                        </label>
                    </div>
                    <BR>
                    <div>
                        <input type="submit" value="上传文件">
                    </div>
                </form>
                </td></tr></table>
            </body>
            </div>
        </html>
        "#,
    )
}

